/**
 * AST 解析网址： https://astexplorer.net/
 * 
 * compiler-dom 核心：
 * template -> render 函数 3个步骤： 
 *  1,把 html 解析成 AST 语法树（AST 语法树描述的是语法本身）
 *  2,转化 ATS 语法树，加标记和进行优化（transform）
 *  3,生成 render 函数（核心字符串的拼接）
 */

export const enum NodeTypes {
  ROOT,
  ElEMENT,
  TEXT,
  SIMPLE_EXPRESSION = 4,
  INTERPOLATION = 5,
  ATTRIBUTE = 6,
  DIRECTIVE = 7,
  COMPOUND_EXPRESSION = 8,
  TEXT_CALL = 12,
  VNODE_CALL = 13,
}

/**
 * 解析是否完成，判断 context.source 是否为空
 * @param context 
 * @returns 
 */
function isEnd(context) {
  const source = context.source;
  return !source;
}

function parseElement(context){
  console.log('处理元素', context)
  return ''
}

function parseInterpolation(context){
  console.log('处理表达式', context)
  return '';
}

function getCursor(context) {
  let {
    line,
    colume,
    offset
  } = context;
  return {
    line,
    colume,
    offset
  }
}

function advancePositionWithMutation(context, s, endIndex) {
  let linesCount = 0; //  行
  let linePos = -1; // 记录换行后的第一个字符的位置
  for (let i = 0; i < endIndex; i++) {
    if (s.charCodeAt(i) == 10) { // \n 符号  '\n'.charCodeAt() === 10
      linesCount++; // 遇到换行符号就 ++
      linePos = i; // 换行后的第一个字符的位置
    }
  }
  // 偏移量
  context.offset += endIndex;
  //  行
  context.line += linesCount;
  // 列
  context.colume = linePos === -1 ? context.colume + endIndex : endIndex - linePos;
}

function advanceBy(context, endIndex) {
  let s = context.source;
  // 计算新的结束位置
  advancePositionWithMutation(context, s, endIndex);
  context.source = s.slice(endIndex);
}

function parseTextData(context, endIndex) {
  const rawText = context.source.slice(0, endIndex);
  advanceBy(context, endIndex); // 不断截取
  return rawText;
}
function getSelection(context, start) {
  let end = getCursor(context);
  return {
    start,
    end,
    source: context.originalSource.slice(start.offset, end.offset)
  }
}
function parseText(context){
  console.log('处理文本', context)
  const endTokens = ['<', '{{'];
  let endIndex = context.source.length;
  for (let i = 0; i < endTokens.length; i++) {
    const index = context.source.indexOf(endTokens[i], 1);
    if (index !== -1 && endIndex > index) {
      endIndex = index;
    }
  }
  // 更新行列信息
  let start = getCursor(context);
  const content = parseTextData(context, endIndex);
  
  return {
    type: NodeTypes.TEXT,
    loc: getSelection(context, start),
    content
  };
}

function parseChildren(context) {
  const nodes = [];

  // 不断截取模板，直至为空结束
  while (!isEnd(context)) {
    const s = context.source; // 当前上下文中的内容
    // 这里只讨论 标签<， 内容abc， 表达式{{}}，不考虑注释和自闭标签等

    let node;
    // 判断第 0 位置是否是 < 表示是标签
    if (s[0] === '<') {
      // 处理元素
      node = parseElement(context);
    } else if(s.startsWith('{{')){
      // 处理表达式
      node = parseInterpolation(context);
    } else {
      // 处理文本
      node = parseText(context);
    }
    
    nodes.push(node);
  }

  return nodes;
}

function createParserContext(content){
  
  return {
    line: 1,
    colume: 1,
    offset: 0,
    source: content, // 不断截取，直到为空为止
    originalSource: content, // 原始模板内容
  }
  
}

/**
 * 将模板转成 AST 语法树
 * @param content 用户的 template 模板
 */
function baseParse(content) {
  // 标识节点的信息，行、列、偏移量 ... 对模板的解析
  const context = createParserContext(content);
  return parseChildren(context);
}

export function baseCompile(template) {
  // 将模板转成 AST 语法树
  const ast = baseParse(template);
  return ast;
}

